From 07b06e9a74e68f64dc198752422335c36398df40 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 8 Sep 2014 22:26:14 -0700 Subject: [PATCH] Add tests exercising the registry source --- src/cargo/sources/registry.rs | 21 +-- src/cargo/util/config.rs | 4 +- tests/fixtures/bar-0.0.1.tar.gz | Bin 0 -> 295 bytes tests/fixtures/foo-0.0.1.tar.gz | Bin 0 -> 274 bytes tests/fixtures/notyet-0.0.1.tar.gz | Bin 0 -> 284 bytes tests/support/mod.rs | 17 +- tests/test_cargo_registry.rs | 239 +++++++++++++++++++++++++++++ tests/tests.rs | 2 + 8 files changed, 259 insertions(+), 24 deletions(-) create mode 100644 tests/fixtures/bar-0.0.1.tar.gz create mode 100644 tests/fixtures/foo-0.0.1.tar.gz create mode 100644 tests/fixtures/notyet-0.0.1.tar.gz create mode 100644 tests/test_cargo_registry.rs diff --git a/src/cargo/sources/registry.rs b/src/cargo/sources/registry.rs index f3e34fe1a..1a46c97be 100644 --- a/src/cargo/sources/registry.rs +++ b/src/cargo/sources/registry.rs @@ -72,14 +72,6 @@ impl<'a, 'b> RegistrySource<'a, 'b> { url.as_slice().to_url().map_err(human) } - /// Translates the HTTP url of the registry to the git URL - fn git_url(&self) -> Url { - let mut url = self.source_id.get_url().clone(); - url.path_mut().unwrap().push("git".to_string()); - url.path_mut().unwrap().push("index".to_string()); - url - } - /// Decode the configuration stored within the registry. /// /// This requires that the index has been at least checked out. @@ -103,7 +95,7 @@ impl<'a, 'b> RegistrySource<'a, 'b> { try!(fs::mkdir_recursive(&self.checkout_path, io::UserDir)); let _ = fs::rmdir_recursive(&self.checkout_path); - let url = self.git_url().to_string(); + let url = self.source_id.get_url().to_string(); let repo = try!(git2::Repository::init(&self.checkout_path)); Ok(repo) } @@ -115,7 +107,7 @@ impl<'a, 'b> RegistrySource<'a, 'b> { /// then ready for inspection. /// /// No action is taken if the package is already downloaded. - fn download_package(&mut self, pkg: &PackageId, url: Url) + fn download_package(&mut self, pkg: &PackageId, url: &Url) -> CargoResult { let dst = self.cache_path.join(url.path().unwrap().last().unwrap() .as_slice()); @@ -132,7 +124,7 @@ impl<'a, 'b> RegistrySource<'a, 'b> { }; // TODO: don't download into memory let resp = try!(handle.get(url.to_string()).exec()); - if resp.get_code() != 200 { + if resp.get_code() != 200 && resp.get_code() != 0 { return Err(internal(format!("Failed to get 200 reponse from {}\n{}", url, resp))) } @@ -235,7 +227,7 @@ impl<'a, 'b> Source for RegistrySource<'a, 'b> { let repo = try!(self.open()); // git fetch origin - let url = self.git_url().to_string(); + let url = self.source_id.get_url().to_string(); let refspec = "refs/heads/*:refs/remotes/origin/*"; let mut remote = try!(repo.remote_create_anonymous(url.as_slice(), refspec)); @@ -265,8 +257,9 @@ impl<'a, 'b> Source for RegistrySource<'a, 'b> { url.path_mut().unwrap().push(format!("{}-{}.tar.gz", package.get_name(), package.get_version())); - let path = try!(self.download_package(package, url).chain_error(|| { - internal(format!("Failed to download package `{}`", package)) + let path = try!(self.download_package(package, &url).chain_error(|| { + internal(format!("Failed to download package `{}` from {}", + package, url)) })); let path = try!(self.unpack_package(package, path).chain_error(|| { internal(format!("Failed to unpack package `{}`", package)) diff --git a/src/cargo/util/config.rs b/src/cargo/util/config.rs index a6c85574e..de382e12c 100644 --- a/src/cargo/util/config.rs +++ b/src/cargo/util/config.rs @@ -156,8 +156,8 @@ impl ConfigValue { fn merge(&mut self, from: ConfigValue) -> CargoResult<()> { match (self, from) { - (me @ &String(..), from @ String(..)) => *me = from, - (me @ &Boolean(..), from @ Boolean(..)) => *me = from, + (&String(..), String(..)) | + (&Boolean(..), Boolean(..)) => {} (&List(ref mut old), List(ref mut new)) => { let new = mem::replace(new, Vec::new()); old.extend(new.move_iter()); diff --git a/tests/fixtures/bar-0.0.1.tar.gz b/tests/fixtures/bar-0.0.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..55b2f5a6c6f79f2e256579bd7d6934d5c9d94e2e GIT binary patch literal 295 zcmV+?0oeW@iwFn+0000217cxvEif)HE-@~2VR9~KdI0T~!ES^g6h&S06~u1ZMG*mY zHQn?xjA_t$wL}Ldz_g2||6X*Gv0cp0PMXMB_#)hdK;9v=(mql`NuD{|Wut0|b;-(< zl+HD;3i`8hwq$Z9DCdPJd6`t~JWrDwaB^N+jFXLWS9@^2L9ZGs|MFq%;O-yrC;CEL zJ&|qEUi>G$@~YRy!rE(G^Ph<&^UHr8K1uZd7Gz=fJ$RHohib@Zx*?jsAr}A74dBgT zTzidc{^zW^WM=;hDnbqZi+LjY|M%2K*$uLX25ET!yu)eeh!nkpb;{`Jf9{SH$&-IG t)`gL}L8#ut5%eB(r@)2RgE3R|X@{pYP2&|3i9{m*op0>t)O-LC0045~k+=W= literal 0 HcmV?d00001 diff --git a/tests/fixtures/foo-0.0.1.tar.gz b/tests/fixtures/foo-0.0.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..bf1fc952707b6f0c12a54dbedb6b9601bb8bbc7f GIT binary patch literal 274 zcmV+t0qy=DiwFn+0000217>e;Eif)HE-@~2VR9~KdI0T}y>bE}6h^6e3Z&ARWQ7GT zRjM?32gib#)$D`?2iBy>`0lb=_&0W|Gb*Rx4tJ>d?t!`YudHANAIC5oH>P$)h^SwH zv2EpAvBRq5{tPb#XeE^@HPRA9*JJ1gtYT{dA?Qh&JJN+d9Fc!a63bA#*1ExvepJ@_ z7xL$W{Tk2_UgKxIqleD_$bVaZ_OCwz*ol7X|DoT!luQT^9FqSf&;H*$|92A>zG!`8 zd(Z#E`wwuEzhY^TNDF>8A36W)Fj<<}k6Bbx>`YUUH$u}yQ2bkkSbNv)x6?tfS+(Cj Y#MGHg^G}e;WHNWp2C$DPmH-X_0Aj3zApigX literal 0 HcmV?d00001 diff --git a/tests/fixtures/notyet-0.0.1.tar.gz b/tests/fixtures/notyet-0.0.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..5b8ae93676d68448bed643fa5b13b68e890a7fb5 GIT binary patch literal 284 zcmV+%0ptE3iwFn+0000218#40d1Z7hFfK4IF)nmraxQ0j0PU5}ZUP|?hdJ{U$VroS z9a#RHdg`U`U_4Mu?WQakz&1_Ockil)+D*KzCc1o=Nd`{*<{Ny-UpC)E1r?j8xSF@7 z@l{M{Kor2fGA-e_O7VAx@mgsqq~sbg;GB0oKo?+}vWbMCk@D)vF7fG%d}GqFiH*m literal 0 HcmV?d00001 diff --git a/tests/support/mod.rs b/tests/support/mod.rs index e257a28d6..8d177ef26 100644 --- a/tests/support/mod.rs +++ b/tests/support/mod.rs @@ -284,12 +284,12 @@ impl Execs { fn match_stdout(&self, actual: &ProcessOutput) -> ham::MatchResult { self.match_std(self.expect_stdout.as_ref(), actual.output.as_slice(), - "stdout", actual.error.as_slice()) + "stdout", actual.error.as_slice()) } fn match_stderr(&self, actual: &ProcessOutput) -> ham::MatchResult { self.match_std(self.expect_stderr.as_ref(), actual.error.as_slice(), - "stderr", actual.output.as_slice()) + "stderr", actual.output.as_slice()) } fn match_std(&self, expected: Option<&String>, actual: &[u8], @@ -505,9 +505,10 @@ pub fn path2url(p: Path) -> Url { Url::from_file_path(&p).unwrap() } -pub static RUNNING: &'static str = " Running"; -pub static COMPILING: &'static str = " Compiling"; -pub static FRESH: &'static str = " Fresh"; -pub static UPDATING: &'static str = " Updating"; -pub static DOCTEST: &'static str = " Doc-tests"; -pub static PACKAGING: &'static str = " Packaging"; +pub static RUNNING: &'static str = " Running"; +pub static COMPILING: &'static str = " Compiling"; +pub static FRESH: &'static str = " Fresh"; +pub static UPDATING: &'static str = " Updating"; +pub static DOCTEST: &'static str = " Doc-tests"; +pub static PACKAGING: &'static str = " Packaging"; +pub static DOWNLOADING: &'static str = " Downloading"; diff --git a/tests/test_cargo_registry.rs b/tests/test_cargo_registry.rs new file mode 100644 index 000000000..6c40e4158 --- /dev/null +++ b/tests/test_cargo_registry.rs @@ -0,0 +1,239 @@ +use std::io::{mod, fs, File}; +use url::Url; +use git2; +use serialize::hex::ToHex; + +use support::{ResultTest, project, execs, cargo_dir}; +use support::{UPDATING, DOWNLOADING, COMPILING}; +use support::paths; +use cargo::util::Sha256; + +use hamcrest::assert_that; + +fn registry_path() -> Path { paths::root().join("registry") } +fn registry() -> Url { Url::from_file_path(®istry_path()).unwrap() } +fn dl_path() -> Path { paths::root().join("dl") } +fn dl_url() -> Url { Url::from_file_path(&dl_path()).unwrap() } + +fn cksum(s: &[u8]) -> String { + let mut sha = Sha256::new(); + sha.update(s); + sha.final().to_hex() +} + +fn setup() { + let config = paths::root().join(".cargo/config"); + fs::mkdir_recursive(&config.dir_path(), io::UserDir).assert(); + File::create(&config).write_str(format!(r#" + [registry] + host = "{reg}" + token = "api-token" + "#, reg = registry()).as_slice()).assert(); + + fs::mkdir(®istry_path(), io::UserDir).assert(); + + // Init a new registry + let repo = git2::Repository::init(®istry_path()).unwrap(); + let mut config = repo.config().unwrap(); + config.set_str("user.name", "name").unwrap(); + config.set_str("user.email", "email").unwrap(); + let mut index = repo.index().unwrap(); + + // Prepare the "to download" artifacts + let foo = include_bin!("fixtures/foo-0.0.1.tar.gz"); + let bar = include_bin!("fixtures/bar-0.0.1.tar.gz"); + let notyet = include_bin!("fixtures/notyet-0.0.1.tar.gz"); + let foo_cksum = dl("pkg/foo/foo-0.0.1.tar.gz", foo); + let bar_cksum = dl("pkg/bar/bar-0.0.1.tar.gz", bar); + dl("pkg/bad-cksum/bad-cksum-0.0.1.tar.gz", foo); + let notyet = dl("pkg/notyet/notyet-0.0.1.tar.gz", notyet); + + // Prepare the registry's git repo + file(&mut index, "config.json", format!(r#" + {{"dl_url":"{}"}} + "#, dl_url()).as_slice()); + file(&mut index, "fo/oX/foo", + format!(r#"{{"name":"foo","vers":"0.0.1","deps":[],"cksum":"{}"}}"#, + foo_cksum).as_slice()); + file(&mut index, "ba/rX/bar", + format!(r#"{{"name":"bar","vers":"0.0.1","deps":["foo|>=0.0.0"],"cksum":"{}"}}"#, + bar_cksum).as_slice()); + file(&mut index, "ba/d-/bad-cksum", + format!(r#"{{"name":"bad-cksum","vers":"0.0.1","deps":[],"cksum":"{}"}}"#, + bar_cksum).as_slice()); + file(&mut index, "no/ty/notyet", + format!(r#"{{"name":"notyet","vers":"0.0.1","deps":[],"cksum":"{}"}}"#, + notyet).as_slice()); + index.remove_path(&Path::new("no/ty/notyet")).unwrap(); + + // Commit! + index.write().unwrap(); + let id = index.write_tree().unwrap(); + let tree = git2::Tree::lookup(&repo, id).unwrap(); + let sig = git2::Signature::default(&repo).unwrap(); + git2::Commit::new(&repo, Some("HEAD"), &sig, &sig, + "Initial commit", &tree, []).unwrap(); + + fn file(index: &mut git2::Index, path: &str, contents: &str) { + let dst = index.path().unwrap().dir_path().dir_path().join(path); + fs::mkdir_recursive(&dst.dir_path(), io::UserDir).assert(); + File::create(&dst).write_str(contents).unwrap(); + index.add_path(&Path::new(path)).unwrap(); + } + + fn dl(path: &str, contents: &[u8]) -> String { + let dst = dl_path().join(path); + fs::mkdir_recursive(&dst.dir_path(), io::UserDir).assert(); + File::create(&dst).write(contents).unwrap(); + cksum(contents) + } +} + +test!(simple { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + foo = ">= 0.0.0" + "#) + .file("src/main.rs", "fn main() {}"); + + assert_that(p.cargo_process("build"), + execs().with_status(0).with_stdout(format!("\ +{updating} registry `{reg}` +{downloading} foo v0.0.1 (the package registry) +{compiling} foo v0.0.1 (the package registry) +{compiling} foo v0.0.1 ({dir}) +", + updating = UPDATING, + downloading = DOWNLOADING, + compiling = COMPILING, + dir = p.url(), + reg = registry()).as_slice())); +}) + +test!(deps { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + bar = ">= 0.0.0" + "#) + .file("src/main.rs", "fn main() {}"); + + assert_that(p.cargo_process("build"), + execs().with_status(0).with_stdout(format!("\ +{updating} registry `{reg}` +{downloading} [..] v0.0.1 (the package registry) +{downloading} [..] v0.0.1 (the package registry) +{compiling} foo v0.0.1 (the package registry) +{compiling} bar v0.0.1 (the package registry) +{compiling} foo v0.0.1 ({dir}) +", + updating = UPDATING, + downloading = DOWNLOADING, + compiling = COMPILING, + dir = p.url(), + reg = registry()).as_slice())); +}) + +test!(nonexistent { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + nonexistent = ">= 0.0.0" + "#) + .file("src/main.rs", "fn main() {}"); + + assert_that(p.cargo_process("build"), + execs().with_status(101).with_stderr("\ +No package named `nonexistent` found (required by `foo`). +Location searched: the package registry +Version required: >= 0.0.0 +")); +}) + +test!(bad_cksum { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + bad-cksum = ">= 0.0.0" + "#) + .file("src/main.rs", "fn main() {}"); + + assert_that(p.cargo_process("build").arg("-v"), + execs().with_status(101).with_stderr("\ +Unable to get packages from source + +Caused by: + Failed to download package `bad-cksum v0.0.1 (the package registry)` from [..] + +Caused by: + Failed to verify the checksum of `bad-cksum v0.0.1 (the package registry)` +")); +}) + +test!(update_registry { + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.0.1" + authors = [] + + [dependencies] + notyet = ">= 0.0.0" + "#) + .file("src/main.rs", "fn main() {}"); + + assert_that(p.cargo_process("build"), + execs().with_status(101).with_stderr("\ +No package named `notyet` found (required by `foo`). +Location searched: the package registry +Version required: >= 0.0.0 +")); + + // Add the package and commit + let repo = git2::Repository::open(®istry_path()).unwrap(); + let mut index = repo.index().unwrap(); + index.add_path(&Path::new("no/ty/notyet")).unwrap(); + let id = index.write_tree().unwrap(); + let tree = git2::Tree::lookup(&repo, id).unwrap(); + let sig = git2::Signature::default(&repo).unwrap(); + let parent = git2::Reference::name_to_id(&repo, "refs/heads/master").unwrap(); + let parent = git2::Commit::lookup(&repo, parent).unwrap(); + git2::Commit::new(&repo, Some("HEAD"), &sig, &sig, + "Another commit", &tree, + [&parent]).unwrap(); + + assert_that(p.process(cargo_dir().join("cargo")).arg("build"), + execs().with_status(0).with_stdout(format!("\ +{updating} registry `{reg}` +{downloading} notyet v0.0.1 (the package registry) +{compiling} notyet v0.0.1 (the package registry) +{compiling} foo v0.0.1 ({dir}) +", + updating = UPDATING, + downloading = DOWNLOADING, + compiling = COMPILING, + dir = p.url(), + reg = registry()).as_slice())); +}) diff --git a/tests/tests.rs b/tests/tests.rs index cc96d9ae1..56133c420 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -4,6 +4,7 @@ extern crate cargo; extern crate git2; extern crate hamcrest; +extern crate serialize; extern crate term; extern crate url; @@ -41,3 +42,4 @@ mod test_cargo_generate_lockfile; mod test_cargo_profiles; mod test_cargo_package; mod test_cargo_build_auth; +mod test_cargo_registry; -- 2.30.2